package com.nccgroup.loggerplusplus.util;

import burp.BurpExtender;
import burp.IExtensionHelpers;
import com.nccgroup.loggerplusplus.LoggerPlusPlus;
import com.nccgroup.loggerplusplus.logentry.LogEntryField;

import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.text.DefaultCaret;
import javax.swing.text.html.HTMLEditorKit;
import java.awt.*;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MoreHelp {
	
	// Read the Content-Type value from the header
	public static String findHeaderContentType(String strHeader){
		String contentType="";
		if(!strHeader.equals("")){
			Pattern MY_PATTERN = Pattern.compile("(?im)^content-type:([\\ \\w\\/\\-\\_\\,]*)"); // just in case, it also includes ",_ " 
			Matcher m = MY_PATTERN.matcher(strHeader);
			if (m.find()) {
				contentType = m.group(1);
			}
		}
		return contentType;
	}
	
	// Read the Content-Type value from the header
	public static String findHeaderContentType(List<String> headers){
		String contentType="";
		for(String strHeader : headers){
			if(!strHeader.equals("")){
				Pattern MY_PATTERN = Pattern.compile("(?im)^content-type:([\\ \\w\\/\\-\\_\\,]*)"); // just in case, it also includes ",_ " 
				Matcher m = MY_PATTERN.matcher(strHeader);
				if (m.find()) {
					contentType = m.group(1);
					break;
				}
			}
		}
		return contentType;
	}
	
	// Show a message to the user
	public static void showMessage(final String strMsg){
		new Thread(new Runnable()
		{
			@Override
			public void run()
			{
				JOptionPane.showMessageDialog(JOptionPane.getFrameForComponent(LoggerPlusPlus.instance.getMainViewController().getUiComponent()), strMsg);
			}
		}).start();
		
	}
	
	// Show a message to the user
	public static void showWarningMessage(final String strMsg){
		new Thread(new Runnable()
		{
			@Override
			public void run()
			{
				JOptionPane.showMessageDialog(JOptionPane.getFrameForComponent(LoggerPlusPlus.instance.getMainViewController().getUiComponent()), strMsg, "Warning", JOptionPane.WARNING_MESSAGE);
			}
		}).start();
		
	}
	
	// Show a message to the user
	public static String showPlainInputMessage(final String strMessage, final String strTitle, final String defaultValue){
			String output = (String)JOptionPane.showInputDialog(JOptionPane.getFrameForComponent(LoggerPlusPlus.instance.getMainViewController().getUiComponent()),
						strMessage,strTitle,JOptionPane.PLAIN_MESSAGE, null, null, defaultValue); 
			if(output==null){
				output = defaultValue;
			}
			return output;	
	}
	
	// Common method to ask a multiple question
	public static Integer askConfirmMessage(final String strTitle, final String strQuestion, String[] msgOptions){
		final Object[] options = msgOptions;
	    final int[] choice = new int[1];
	    choice[0] = 0;
	    choice[0] = JOptionPane.showOptionDialog(null,
					strQuestion,
					strTitle,
					JOptionPane.YES_NO_CANCEL_OPTION,
					JOptionPane.QUESTION_MESSAGE,
					null,
					options,
					options[0]);
	    return choice[0];
	}
	
	// Split header and body of a request or response
	public static String[] getHeaderAndBody(byte[] fullMessage,String encoding) throws UnsupportedEncodingException{
		String[] result = {"",""};
		String strFullMessage = "";
		if(fullMessage != null){
			// splitting the message to retrieve the header and the body
			strFullMessage = new String(fullMessage,encoding);
			if(strFullMessage.contains("\r\n\r\n"))
				result = strFullMessage.split("\r\n\r\n",2);
		}
		return result;
	}

//	public static void checkForUpdate(boolean showMessages) {
//		new Thread(() -> {
//			IExtensionHelpers helper = LoggerPlusPlus.callbacks.getHelpers();
//			Double currenVersion = Globals.VERSION;
//			Double latestVersion = 0.0;
//			int updateStatus = -1;
//			String updateMessage = "";
//
//			try {
//				URL changeLogURL = new URL(Globals.CHANGELOG);
//				byte[] request = helper.buildHttpRequest(changeLogURL);
//				byte[] response = LoggerPlusPlus.callbacks.makeHttpRequest(changeLogURL.getHost(), 443, true, request);
//
//				if (response != null) {
//					// splitting the message to retrieve the header and the body
//					String strFullMessage = new String(response, StandardCharsets.UTF_8);
//					if (strFullMessage.contains("\r\n\r\n")) {
//						String strBody = strFullMessage.split("\r\n\r\n", 2)[1];
//						Pattern MY_PATTERN = Pattern.compile("(?im)^[\\s]*v[\\s]*(\\d+(\\.*\\d*){0,1})$");
//
//						Matcher m = MY_PATTERN.matcher(strBody);
//
//						if (m.find()) {
//							latestVersion = Double.parseDouble(m.group(1));
//
//							if (latestVersion > currenVersion) {
//								updateStatus = 1; // update is available
//							} else if (latestVersion.equals(currenVersion)) {
//								updateStatus = 0; // no update is available
//							} else {
//								updateStatus = 2; // Future version!
//							}
//						}
//					}
//
//				}
//			} catch (Exception e) {
//				LoggerPlusPlus.callbacks.printError(e.getMessage());
//			}
//
//			switch (updateStatus) {
//				case -1:
//					updateMessage = "Check for update failed: Could not get a proper response from " + Globals.CHANGELOG;
//					LoggerPlusPlus.callbacks.printError(updateMessage);
//					break;
//				case 0:
//					updateMessage = "This version is up to date.";
//					LoggerPlusPlus.callbacks.printOutput(updateMessage);
//					break;
//				case 1:
//					updateMessage = "Version " + latestVersion.toString() + " is available via GitHub. Visit the extension homepage.";
//					if (LoggerPlusPlus.callbacks.isExtensionBapp()) {
//						updateMessage += "\nAs you are using BApp Store, you have to remove it first and download the Jar file from the GitHub repository. ";
//					} else {
//						if (LoggerPlusPlus.callbacks.getExtensionFilename() != null) {
//							int res = MoreHelp.askConfirmMessage("Update Available", "An update is available. Would you like to update now?", new String[]{"Yes", "No"});
//							if (res == JOptionPane.OK_OPTION) {
//								try {
//									//TODO FIXME
//									URL updateUrl = new URL(Globals.UPDATE_URL);
//									InputStream input = updateUrl.openStream();
//									Path outputPath = Paths.get(LoggerPlusPlus.callbacks.getExtensionFilename());
//									Files.copy(input, outputPath, StandardCopyOption.REPLACE_EXISTING);
//								} catch (Exception e) {
//									MoreHelp.showMessage("Could not update the plugin. Please visit the extension page to update manually.");
//									return;
//								}
//								MoreHelp.showMessage("Update complete. Re-enable the plugin in the extensions tab to continue.");
//								LoggerPlusPlus.callbacks.unloadExtension();
//								return;
//							}
//						}
//					}
//					LoggerPlusPlus.callbacks.printOutput(updateMessage);
//					break;
//				case 2:
//					updateMessage = "This version is more up to date than the GitHub version! Are you a time traveler? or just a keen ninja? ;)";
//					LoggerPlusPlus.callbacks.printOutput(updateMessage);
//					break;
//			}
//			if (!showMessages) return;
//			MoreHelp.showMessage(updateMessage);
//		}).start();
//	}

	public static void showLargeOutputDialog(String title, String output){
		JTextPane outputArea = new JTextPane();
		outputArea.setEditorKit(new HTMLEditorKit());
		outputArea.setText(output);
		outputArea.setCaretPosition(0);
		JScrollPane scrollPane = new JScrollPane(outputArea);
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		scrollPane.setPreferredSize(new Dimension((int) (screenSize.getWidth()/2.0), (int) (screenSize.getHeight()/2.0)));
		scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		JOptionPane.showMessageDialog(JOptionPane.getFrameForComponent(LoggerPlusPlus.instance.getMainViewController().getUiComponent()), scrollPane, title, JOptionPane.PLAIN_MESSAGE);
	}

	public static String showLargeInputDialog(String title, String message){
		return JOptionPane.showInputDialog(title);
	}

	public static File getSaveFile(String filename, String formatDescription, String extension) throws Exception {
		JFileChooser chooser = null;
		FileNameExtensionFilter filter = new FileNameExtensionFilter("JSON Format (JSON)", "json");

		chooser = new JFileChooser();
		chooser.setDialogTitle("Saving Logger++ Entries");
		chooser.setFileFilter(filter);
		chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
		chooser.setSelectedFile(new File(filename));
		chooser.setAcceptAllFileFilterUsed(false);

		int val = chooser.showSaveDialog(null);

		if (val == JFileChooser.APPROVE_OPTION) {
			return chooser.getSelectedFile();
		}

		throw new Exception("Operation cancelled.");
	}

	public static List<LogEntryField> showFieldChooserDialog(JComponent owner, String title, List<LogEntryField> defaultFields) throws Exception {
		FieldSelectorDialog fieldSelectorDialog = new FieldSelectorDialog(JOptionPane.getFrameForComponent(owner), title, defaultFields);
		fieldSelectorDialog.setVisible(true);

		List<LogEntryField> selectedFields = fieldSelectorDialog.getSelectedFields();
		if(selectedFields.isEmpty()) {
			return null;
		}

		return selectedFields;
	}
}
